package net.mingsoft.report_data.biz.impl.report_gen;

import com.alibaba.fastjson.JSON;
import net.mingsoft.basic.util.DateUtil;
import net.mingsoft.report_data.biz.ZkDataFocusAreaBiz;
import net.mingsoft.report_data.constant.ZkDataConstant;
import net.mingsoft.report_data.enums.ReportPeriodType;
import net.mingsoft.report_data.sao.SgSao;
import net.mingsoft.report_data.sao.entity.*;
import net.mingsoft.report_data.util.PeriodUtil;
import net.mingsoft.report_data.util.ReportFtlRender;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author gengfa
 * @date 22/06/01
 */
@Service("FOCUS_AREA")
public class ZkDataFocusAreaBizImpl implements ZkDataFocusAreaBiz {

    @Resource
    SgSao sgSao;

    @Resource
    FreeMarkerConfigurer configurer;

    private static final String HAINAN_FOCUS_AREA = "海南省关注区域";
    private static final String SCENIC_TOP5 = "景区Top5";
    private static final String TRAFFIC_TOP5 = "交通Top5";
    private static final String OTHER_TOP5 = "其他Top5";

    private static final String DESC_SUMMARY = "截至目前，关注区域总数共{}个，其中关注景区有{}个，关注的交通枢纽有{}个，未分类的其他区域共{}个，下图所示为关注区域在海南省内各市县分布情况。";
    private static final String DESC_SCENIC = "选取关注区域为景区类型的区域，统计本周累计用户数，用户数量从多到少排行前5的区域如下图所示，{}累计用户数量为{}，排名第一，其次是{}，累计用户数量共{}，{}排名第三，累计用户数量为{}。";
    private static final String DESC_TRAFFIC = "选取关注区域为交通枢纽类型的区域，统计本周累计用户数，用户数量从多到少排行前5的区域如下图所示，{}累计用户数量为{}，排名第一，其次是{}，累计用户数量共{}，{}排名第三，累计用户数量为{}。";
    private static final String DESC_OTHER = "选取关注区域为其他类型的区域，统计本周累计用户数，用户数量从多到少排行前5的区域如下图所示，{}累计用户数量为{}，排名第一，其次是{}，累计用户数量共{}，{}排名第三，累计用户数量为{}。";

    @Override
    public String generate(ReportPeriodType periodType) {
        Map<String, Object> map = PeriodUtil.getDateArgs(periodType);
        getSummary(map);
        getSceneUserTop5(map);
        getTrafficUserTop5(map);
        getOtherAreaUserTop5(map);
        getAreaChangingState(map);
        return ReportFtlRender.render(configurer, "report/form-gzqyfx.ftl", map);
    }

    @Override
    public Map<String, Object> getSummary(Map<String, Object> map) {
        // 获取主体数据
        AllTopDataEntity allTopData = sgSao.getAllTopData();
        // 获取市县字典
        Map<Integer, String> provinceDict = sgSao.getProvinceDictionary();
        // 4 part
        Map<String, FocusAreaDto> focusAreaMap = allTopData.getData().stream().collect(Collectors.toMap(FocusAreaDto::getDesc, o -> o));
        List<Map<String, Object>> focusAreaMapList = focusAreaMap.get(HAINAN_FOCUS_AREA).getMap().entrySet().stream()
                .collect(Collectors.toMap(o -> provinceDict.get(o.getKey()), o -> o.getValue().size())).entrySet().stream()
                .map(o -> {
                    Map<String, Object> m = new HashMap<>(16);
                    m.put(ZkDataConstant.PROP_NAME, o.getKey());
                    m.put(ZkDataConstant.PROP_VALUE, o.getValue());
                    return m;
                }).collect(Collectors.toList());
        map.put("focusAreaCityCountMap", JSON.toJSONString(focusAreaMapList));
        map.put("focusAreaCityCountMapDesc", MessageFormatter.arrayFormat(DESC_SUMMARY,
                new String[]{
                        String.valueOf(focusAreaMap.get(HAINAN_FOCUS_AREA).getAllCount()),
                        String.valueOf(focusAreaMap.get(SCENIC_TOP5).getAllCount()),
                        String.valueOf(focusAreaMap.get(TRAFFIC_TOP5).getAllCount()),
                        String.valueOf(focusAreaMap.get(OTHER_TOP5).getAllCount())
                }).getMessage());
        return map;
    }

    @Override
    public Map<String, Object> getSceneUserTop5(Map<String, Object> map) {
        // 获取主体数据
        AllTopDataEntity allTopData = sgSao.getAllTopData();
        // 4 part
        Map<String, FocusAreaDto> focusAreaMap = allTopData.getData().stream().collect(Collectors.toMap(FocusAreaDto::getDesc, o -> o));
        List<AreaDetailDto> focusAreaScenicTop5 = focusAreaMap.get(SCENIC_TOP5).getData();
        map.put("focusAreaScenicTop5", JSON.toJSONString(focusAreaScenicTop5));
        map.put("focusAreaScenicTop5Desc", MessageFormatter.arrayFormat(DESC_SCENIC,
                new String[]{
                        focusAreaScenicTop5.get(0).getAreaName(),
                        String.valueOf(focusAreaScenicTop5.get(0).getCount()),
                        focusAreaScenicTop5.get(1).getAreaName(),
                        String.valueOf(focusAreaScenicTop5.get(1).getCount()),
                        focusAreaScenicTop5.get(2).getAreaName(),
                        String.valueOf(focusAreaScenicTop5.get(2).getCount()),
                }).getMessage());
        return map;
    }

    @Override
    public Map<String, Object> getTrafficUserTop5(Map<String, Object> map) {
        // 获取主体数据
        AllTopDataEntity allTopData = sgSao.getAllTopData();
        // 4 part
        Map<String, FocusAreaDto> focusAreaMap = allTopData.getData().stream().collect(Collectors.toMap(FocusAreaDto::getDesc, o -> o));
        List<AreaDetailDto> focusAreaTrafficTop5 = focusAreaMap.get(TRAFFIC_TOP5).getData();
        map.put("focusAreaTrafficTop5", JSON.toJSONString(focusAreaTrafficTop5));
        map.put("focusAreaTrafficTop5Desc", MessageFormatter.arrayFormat(DESC_TRAFFIC,
                new String[]{
                        focusAreaTrafficTop5.get(0).getAreaName(),
                        String.valueOf(focusAreaTrafficTop5.get(0).getCount()),
                        focusAreaTrafficTop5.get(1).getAreaName(),
                        String.valueOf(focusAreaTrafficTop5.get(1).getCount()),
                        focusAreaTrafficTop5.get(2).getAreaName(),
                        String.valueOf(focusAreaTrafficTop5.get(2).getCount()),
                }).getMessage());
        return map;
    }

    @Override
    public Map<String, Object> getOtherAreaUserTop5(Map<String, Object> map) {
        // 获取主体数据
        AllTopDataEntity allTopData = sgSao.getAllTopData();
        // 4 part
        Map<String, FocusAreaDto> focusAreaMap = allTopData.getData().stream().collect(Collectors.toMap(FocusAreaDto::getDesc, o -> o));
        List<AreaDetailDto> focusAreaOtherTop5 = focusAreaMap.get(OTHER_TOP5).getData();
        map.put("focusAreaOtherTop5", JSON.toJSONString(focusAreaOtherTop5));
        map.put("focusAreaOtherTop5Desc", MessageFormatter.arrayFormat(DESC_OTHER,
                new String[]{
                        focusAreaOtherTop5.get(0).getAreaName(),
                        String.valueOf(focusAreaOtherTop5.get(0).getCount()),
                        focusAreaOtherTop5.get(1).getAreaName(),
                        String.valueOf(focusAreaOtherTop5.get(1).getCount()),
                        focusAreaOtherTop5.get(2).getAreaName(),
                        String.valueOf(focusAreaOtherTop5.get(2).getCount()),
                }).getMessage());
        return map;
    }

    private static final String DESC_AREA_CHANGING_P1 = "近一周累计用户数为{}人，其中常住用户数为{}人，流动用户数为{}人，特定用户数为{}人，外省用户数为{}人，境外用户数为{}人，占比如下图所示。";
    private static final String DESC_AREA_CHANGING_P2 = "下图所示为近一周在线用户变化情况，如图所示，本周每日累计在线用户数量峰值出现在{},累计在线用户数量为{}人。";
    private static final List<String> FILTER_FOCUS_AREA = Arrays.asList("骑楼老街", "南山文化旅游区", "海南白石岭旅游景区", "尖峰岭国家森林公园", "呀诺达热带雨林", "美兰机场", "海口秀英港", "海口东站", "凤凰机场", "三亚港", "海南省人民政府", "五源河体育馆", "三亚市人民政府", "琼海市人民政府", "文昌市人民政府");

    @Override
    public Map<String, Object> getAreaChangingState(Map<String, Object> map) {
        // 获取当前所有关注区域
        AllTopDataEntity allTopData = sgSao.getAllTopData();
        List<FocusAreaDto> allFocusAreaData = allTopData.getData();
        List<FocusAreaDto> haiNanAreaList =
                allFocusAreaData.stream().filter(o -> o.getDesc().equals(HAINAN_FOCUS_AREA)).collect(Collectors.toList());
        Map<Integer, List<AreaDetailDto>> haiNanFocusAreaMap = haiNanAreaList.get(0).getMap();
        List<AreaDetailDto> allHainanAreaDtoList = new ArrayList<>();
        haiNanFocusAreaMap.forEach((key, value) -> allHainanAreaDtoList.addAll(value));

        // 根据区域ID和任务ID获取详情
        List<FocusAreaResponse> areaResponseList = new ArrayList<>();
        allHainanAreaDtoList.stream().filter(o->FILTER_FOCUS_AREA.contains(o.getAreaName())).forEach(area -> {
            // 根据区域ID和任务ID获取 -> 重点区域实时监测-查询实时在线用户数 (/areaMonitoring/getCurrentUser)
            CurrentUserDto currentUserDto = sgSao.getCurrentUser(area.getAreaId(), area.getTaskId());
            // 根据区域ID和任务ID获取 -> 重点区域-查询实时在线用户数曲线 (/areaMonitoring/getAreaUserUp)
            AreaUserUpDto areaUserUp = sgSao.getAreaUserUp(area.getAreaId(), area.getTaskId());
            // 排序处理
            areaUserUp.getOneHourList().sort(Comparator.comparing(CountPeriodDto::getPeriod));
            areaUserUp.getTwentyFourHourList().sort(Comparator.comparing(CountPeriodDto::getPeriod));
            areaUserUp.getSevenDaysList().sort(Comparator.comparing(CountPeriodDto::getPeriod));

            // 描述文本 部分1
            String descP1 = MessageFormatter.arrayFormat(DESC_AREA_CHANGING_P1, new String[]{
                    String.valueOf(currentUserDto.getTotalUsers()),
                    String.valueOf(currentUserDto.getPermanentUsers()),
                    String.valueOf(currentUserDto.getMobileUsers()),
                    String.valueOf(currentUserDto.getSpecificUsers()),
                    String.valueOf(currentUserDto.getOtherProvincesUsers()),
                    String.valueOf(currentUserDto.getOverseasUsers())
            }).getMessage();

            CountPeriodDto maxCountPeriodDto = areaUserUp.getSevenDaysList().stream().max(Comparator.comparing(CountPeriodDto::getCount)).get();
            String descP2 = MessageFormatter.arrayFormat(DESC_AREA_CHANGING_P2, new String[]{
                    DateUtil.transferDateFormat(maxCountPeriodDto.getPeriod(), DateUtil.DATE_FORMAT_STR, DateUtil.DATE_FORMAT_MONTH_DAY_CN),
                    String.valueOf(maxCountPeriodDto.getCount())
            }).getMessage();

            areaResponseList.add(new FocusAreaResponse()
                    .setAreaId(area.getAreaId())
                    .setTaskId(area.getTaskId())
                    .setAreaName(area.getAreaName())
                    .setAreaUserUp(areaUserUp)
                    .setCurrentUser(currentUserDto)
                    .setDescP1(descP1)
                    .setDescP2(descP2));

        });

        // 输出到模板
        map.put("focusAreaResponseList", JSON.toJSONString(areaResponseList));
        return map;
    }
}
